/**
 * SudoStruct.java
 */
package tk.sunlatus.game.sudo;

import java.util.HashSet;
import java.util.Set;

/**
 * @author Sunlotus
 * 
 */
public class SudoStruct {
    public static final int STATUS_LOCK = 1;

    public static final int STATUS_EMPTY = 0;

    public static final int STATUS_FILL = 2;

    private Set<Integer> checker = new HashSet<Integer>();
    private boolean needInit = false;
    private int[][] sudo = new int[9][9];

    private int[][] sudoStatus = new int[9][9];

    public int[][] getSudo() {
        return sudo;
    }

    public void setSudo(int[][] sudo) {

        // 初始化棋盘，并记录每个方格的状态，
        // 1：为系统生成值,0:为空格，2为用户填写值
        for (int i = 0; i < sudo.length; i++) {
            for (int j = 0; j < sudo.length; j++) {
                if (sudo[i][j] > 0 && sudo[i][j] < 10) {
                    this.sudo[i][j] = sudo[i][j];
                    getSudoStatus()[i][j] = STATUS_LOCK;
                } else {
                    getSudoStatus()[i][j] = STATUS_EMPTY;
                }
            }
        }
    }

    public void fill(int x, int y, int value) {
        if (x > 9 || x < 1) {
            System.out.println("x mast in [1,9]");
            return;
        }
        if (y > 9 || y < 0) {
            System.out.println("x mast in [1,9]");
            return;
        }
        if (STATUS_LOCK == getSudoStatus()[getIndex(x)][getIndex(y)]) {
            System.out.println("can't set " + value + " to [" + x + "][" + y + "]");
        } else if (value != 0) {
//            System.out.println("****\t\tset " + value + " to [" + x + "][" + y + "]");
            getSudoStatus()[getIndex(x)][getIndex(y)] = STATUS_FILL;
            sudo[getIndex(x)][getIndex(y)] = value;
        } else {
            getSudoStatus()[getIndex(x)][getIndex(y)] = STATUS_EMPTY;
            sudo[getIndex(x)][getIndex(y)] = value;
        }
    }

    private int getIndex(int num) {
        return num - 1;
    }

    public void show(int[][] sudo) {
        System.out.println("*******start********");
        for (int i = 0; i < sudo.length; i++) {
            for (int j = 0; j < sudo[i].length; j++) {
                System.out.print(sudo[i][j]);
            }
            System.out.println();
        }
        System.out.println("*******end********");

    }

    public boolean isNotEmpty(int x, int y) {
        return STATUS_EMPTY != getSudoStatus()[getIndex(x)][getIndex(y)];
    }

    public int getLocationX(int x) {
        return x % 3 == 0 ? (x - 1) / 3 : x / 3;
    }

    public int getLocationY(int y) {
        return getLocationX(y);
    }

    public int get(int x, int y) {
        return sudo[getIndex(x)][getIndex(y)];
    }

    public int[][] getSudoStatus() {
        return sudoStatus;
    }

    public void setSudoStatus(int[][] sudoStatus) {
        this.sudoStatus = sudoStatus;
    }

    public boolean isNotAllFill() {
        for (int x = 1; x < 10; x++) {
            for (int y = 1; y < 10; y++) {
                if (isEmpty(x, y)) {
                    return true;
                }
            }
        }
        return false;
    }

    private boolean isEmpty(int x, int y) {
        return STATUS_EMPTY == getSudoStatus()[getIndex(x)][getIndex(y)];
    }

    /**
     * 方法描述：检查（x,y）位置的值在x行是否合法
     * 
     * @param x
     * @param y
     */
    private void checkX(int x, int y) {
        Set<Integer> nums = initChecker();
        for (int i = 0; i < getSudo()[x - 1].length; i++) {
            if (nums.contains(getSudo()[x - 1][i])) {
                nums.remove(getSudo()[x - 1][i]);
            }
        }
    }

    private void checkY(int x, int y) {
        Set<Integer> nums = initChecker();
        if (isNotEmpty(x, y)) {
            nums.remove(get(x, y));
        }
        for (int i = 0; i < getSudo().length; i++) {
            if (nums.contains(getSudo()[i][y - 1])) {
                nums.remove(getSudo()[i][y - 1]);
            }
        }

    }

    /**
     * 方法描述：检查（x,y）位置的值在9宫格中是否合法
     * 
     * @param x
     * @param y
     */
    private void checkXY(int x, int y) {
        Set<Integer> nums = initChecker();
        int sudox = getLocationX(x);
        int sudoy = getLocationY(y);
        for (int i = 0; i < 3; i++) {
            for (int j = 0; j < 3; j++) {
                nums.remove(get(sudox * 3 + i + 1, sudoy * 3 + j + 1));
            }
        }
    }

    /**
     * 方法描述： 检查之后的可用值
     * 
     * @return
     */
    private Set<Integer> initChecker() {
        if (needInit) {
            checker.clear();
            for (int i = 0; i < 9; i++) {
                checker.add(i + 1);
            }
        }
        return checker;
    }

    /**
     * 方法描述：检查棋盘中的值是否合法
     * 
     * @return
     */
    public boolean isValid() {

        for (int i = 0; i < 9; i++) {
            for (int j = 0; j < 9; j++) {
                if (isNotEmpty(i + 1, j + 1)) {
                    continue;
                }
                needInit = true;
                checkX(i + 1, j + 1);
                needInit = false;
                checkY(i + 1, j + 1);
                checkXY(i + 1, j + 1);
                if (checker.size() == 0) {
                    return false;
                }
            }
        }
        return true;
    }
}
